package com.cndw.kungfu.comm.tencent;

import java.util.HashMap;
import java.util.Map;

import com.cndw.kungfu.config.ConstantsConfig;
import com.cndw.kungfu.config.ConstantsIntKey;
import com.cndw.kungfu.config.ConstantsSystem;
import com.cndw.kungfu.domain.Player;
import com.cndw.kungfu.ext.CommUtil;
import com.cndw.kungfu.ext.LogUtil;
import com.cndw.kungfu.ext.TimeProcesser;
import com.cndw.kungfu.model.Context;
import com.cndw.rpg.framework.SessionHolder;
import com.qq.opensns.datacollector.DatacollectorClient;
import com.qq.opensns.datacollector.LogType;

public class QQDC {

	private static QQDC instance = null;

	private static DatacollectorClient client;

	public static final int appId = 100622837;

	private final boolean isOpenDC;

	private int size = 0;

	private long svrip = 0;

	private static final char symbolEqual = '=';

	private static final char symbolAddress = '&';

	public static QQDC getInstance() {
		if (instance == null) {
			synchronized (QQDC.class) {
				if (instance == null) {
					instance = new QQDC();
				}
			}
		}
		return instance;
	}

	private QQDC() {
		isOpenDC = ConstantsConfig.getSysCgPartnerEName().equals("tencent");
		if (isOpenDC) {
			client = DatacollectorClient.init("appoperlog");
		}
		size = LogField.values().length;
		svrip = CommUtil.ipToLong(ConstantsSystem.getHostAddress());
		LogUtil.getQQDC().debug("appId:" + appId + " isOpenDC:" + isOpenDC + " ");
	}

	public boolean isOpenDC() {
		return isOpenDC;
	}

	private Map<LogField, Object> getIntMap() {
		Map<LogField, Object> map = new HashMap<LogField, Object>(size, 1);

		for (LogField e : LogField.values()) {
			map.put(e, "");
		}

		map.put(LogField.version, 1);
		map.put(LogField.appid, appId);
		map.put(LogField.svrip, svrip);
		map.put(LogField.time, TimeProcesser.getUnixTime());
		map.put(LogField.worldid, ConstantsConfig.getSysCgWorldId());

		return map;
	}

	private Map<LogField, Object> getIntMap(Player player) {
		Map<LogField, Object> map = getIntMap();
		map.put(LogField.domain, QQConstants.getDomain(player.getPlatform()));
		map.put(LogField.userip, CommUtil.ipToLong(player.getLastIp()));
		map.put(LogField.opuid, player.getPlayerId());
		map.put(LogField.opopenid, player.getAccountName());
		map.put(LogField.level, player.getLevel());
		map.put(LogField.source, player.getPlatform());
		map.put(LogField.key, player.getDataInfo().getOpenKey());

		map.put(LogField.totalcoin, player.getAsset());
		map.put(LogField.totalexp, player.getExp());
		map.put(LogField.totalfee, player.getGoldAll() * 10);

		return map;
	}

	public void login(Player player) {
		if (!isOpenDC()) {
			return;
		}
		Map<LogField, Object> map = getIntMap(player);

		map.put(LogField.optype, LogFieldType.cRead);
		map.put(LogField.actionid, LogFieldType.login);

		wirteLog(map);
	}

	public void reg(Player player) {
		if (!isOpenDC()) {
			return;
		}
		Map<LogField, Object> map = getIntMap(player);

		map.put(LogField.optype, LogFieldType.cWirte);
		map.put(LogField.actionid, LogFieldType.reg);

		wirteLog(map);
	}

	public void logOut(Player player) {
		if (!isOpenDC()) {
			return;
		}
		Map<LogField, Object> map = getIntMap(player);

		map.put(LogField.optype, LogFieldType.cRead);
		map.put(LogField.actionid, LogFieldType.logout);
		map.put(LogField.onlinetime, TimeProcesser.getUnixTime() - player.getLastLogin());

		wirteLog(map);
	}

	public void onLine() {
		if (!isOpenDC()) {
			return;
		}

		int[] currentOnline = { 0, 0, 0, 0, 0, 0, 0, 0 };
		int onLine = SessionHolder.getInstance().onlineNums();
		if (onLine > 0) {
			Map<String, Integer> dataMap = Context.getBusinessServer().getOnLine(1800);

			if (dataMap != null && !dataMap.isEmpty()) {
				if (dataMap.containsKey(QQConstants.qzone)) {
					currentOnline[1] += dataMap.get(QQConstants.qzone);
				}
				if (dataMap.containsKey(QQConstants.pengyou)) {
					currentOnline[2] += dataMap.get(QQConstants.pengyou);
				}
				if (dataMap.containsKey(QQConstants.qplus)) {
					currentOnline[3] += dataMap.get(QQConstants.qplus);
				}
				if (dataMap.containsKey(QQConstants.pf3366)) {
					currentOnline[4] += dataMap.get(QQConstants.pf3366);
				}
			}
		}
		LogUtil.getQQDC()
				.debug("online " + onLine + " -> " + currentOnline[1] + " | " + currentOnline[2] + " | " + currentOnline[3] + " | " + currentOnline[4]);

		Map<LogField, Object> map = getIntMap();
		map.put(LogField.optype, LogFieldType.cOther);
		map.put(LogField.actionid, LogFieldType.online);
		map.put(LogField.opuid, ConstantsConfig.getSysCgWorldId());
		map.put(LogField.opopenid, ConstantsConfig.getSysCgWorldId());

		map.put(LogField.domain, QQConstants.getDomain(QQConstants.qzone));
		map.put(LogField.user_num, currentOnline[1]);// 上报空间在线
		wirteLog(map);

		map.put(LogField.domain, QQConstants.getDomain(QQConstants.pengyou));
		map.put(LogField.user_num, currentOnline[2]);// 上报朋友在线
		wirteLog(map);

		map.put(LogField.domain, QQConstants.getDomain(QQConstants.qplus));
		map.put(LogField.user_num, currentOnline[3]);// 上报q+在线
		wirteLog(map);
		map.put(LogField.domain, QQConstants.getDomain(QQConstants.pf3366));
		map.put(LogField.user_num, currentOnline[4]);// 上报3366在线
		wirteLog(map);
	}

	public void pay(Player player, int goldGot) {
		if (!isOpenDC()) {
			return;
		}

		Map<LogField, Object> map = getIntMap(player);
		map.put(LogField.optype, LogFieldType.cPay);
		map.put(LogField.actionid, LogFieldType.payGot);
		map.put(LogField.modifyfee, goldGot);

		wirteLog(map);

	}

	public void cost(Player player, int cost, int eventId) {
		cost(player, cost, eventId, 888, 1);
	}

	public void cost(Player player, int cost, int itemid, int itemcnt) {
		cost(player, cost, itemid, 999, itemcnt);
	}

	public void cost(Player player, int cost, int itemid, int itemtype, int itemcnt) {

		if (!isOpenDC() || player.getDataInfo().isGmLogin()) {
			return;
		}

		Map<LogField, Object> map = getIntMap(player);
		if (player.getDataInfo().intDataGet(ConstantsIntKey.payTrue) == 1) {
			map.put(LogField.optype, LogFieldType.cPay);
			map.put(LogField.actionid, LogFieldType.payCost);
		} else {
			map.put(LogField.optype, LogFieldType.cPay);
			map.put(LogField.actionid, LogFieldType.payFree);
		}

		map.put(LogField.modifyfee, -cost * 10);
		map.put(LogField.itemid, itemid);
		map.put(LogField.itemtype, itemtype);
		map.put(LogField.itemcnt, itemcnt);

		wirteLogAsync(map);
	}

	/**
	 * 上传点击事件
	 * 
	 * @param player
	 * @param actionId
	 */
	public void logClick(Player player, int actionId) {
		if (!isOpenDC() || player.getDataInfo().isGmLogin()) {
			return;
		}

		Map<LogField, Object> map = getIntMap(player);
		map.put(LogField.optype, LogFieldType.cOther);
		map.put(LogField.actionid, actionId);
		wirteLogAsync(map);
	}

	public void logClick(LoginObj loginObj, String ip, int actionId) {
		if (!isOpenDC()) {
			return;
		}

		Map<LogField, Object> map = getIntMap();
		map.put(LogField.domain, QQConstants.getDomain(loginObj.getPf()));
		map.put(LogField.userip, CommUtil.ipToLong(ip));
		map.put(LogField.opuid, 0);
		map.put(LogField.opopenid, loginObj.getOpenId());
		map.put(LogField.level, 0);
		map.put(LogField.source, loginObj.getPf());
		map.put(LogField.key, loginObj.getOpenKey());

		map.put(LogField.optype, LogFieldType.cOther);
		map.put(LogField.actionid, actionId);
		wirteLogAsync(map);
	}

	private void wirteLogAsync(Map<LogField, Object> map) {

		try {
			StringBuilder sb = new StringBuilder();
			for (Map.Entry<LogField, Object> entry : map.entrySet()) {
				if (entry.getValue() == null) {
					LogUtil.getQQDC().debug("null " + entry.getKey());
					continue;
				}
				sb.append(entry.getKey()).append(symbolEqual).append((entry.getValue().toString())).append(symbolAddress);
			}
			sb.delete(sb.length() - 1, sb.length());
			final String obj = sb.toString();

			Context.getTimerServer().execute(new Runnable() {

				@Override
				public void run() {
					try {
						client.writeBaseLog(LogType.LT_NORMAL, obj, true);
					} catch (Exception e) {
						LogUtil.getQQDC().error("QQDC ERR: " + e.getMessage());
					}

				}
			});

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void wirteLog(Map<LogField, Object> map) {

		try {
			StringBuilder sb = new StringBuilder();
			for (Map.Entry<LogField, Object> entry : map.entrySet()) {
				sb.append(entry.getKey()).append('=').append((entry.getValue().toString())).append('&');
			}
			sb.delete(sb.length() - 1, sb.length());

			client.writeBaseLog(LogType.LT_NORMAL, sb.toString(), true);
		} catch (Exception e) {
			// e.printStackTrace();
			LogUtil.getQQDC().error("QQDC ERR: " + e.getMessage());
		}
	}

}
